﻿using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace PointAndPolygon
{
	public partial class MainGUI : Form
	{
		/// <summary>
		/// 是否正在画
		/// </summary>
		private bool isDrawing = false;

		/// <summary>
		/// 当前正在画第几个点
		/// </summary>
		private int currentIndex = 0;

		/// <summary>
		/// 记录每一趟画的点
		/// </summary>
		private Point[] points = new Point[5];

		/// <summary>
		/// 画布
		/// </summary>
		private Graphics graphics;

		/// <summary>
		/// 多边形边长笔
		/// </summary>
		private Pen linePen = new Pen(Color.Blue, 1.5f);

		/// <summary>
		/// 多边形点笔刷
		/// </summary>
		private Brush polygonBrush = new SolidBrush(Color.Red);

		/// <summary>
		/// 末端点笔刷
		/// </summary>
		private Brush endPointBrush = new SolidBrush(Color.Magenta);

		public MainGUI()
		{
			InitializeComponent();
			graphics = showArea.CreateGraphics();
			graphics.SmoothingMode = SmoothingMode.HighQuality;
			graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
		}

		/// <summary>
		/// 向量叉乘
		/// </summary>
		/// <param name="v1">向量1，用长度为二的点数组表示，第一个元素为起始点，二个为终止点</param>
		/// <param name="v2">向量2，用长度为二的点数组表示，第一个元素为起始点，二个为终止点</param>
		/// <returns>叉乘结果</returns>
		private int vectorCrossProduct(Point[] v1, Point[] v2)
		{
			int x1 = v1[1].X - v1[0].X;
			int x2 = v2[1].X - v2[0].X;
			int y1 = v1[1].Y - v1[0].Y;
			int y2 = v2[1].Y - v2[0].Y;
			return x1 * y2 - x2 * y1;
		}

		private void showArea_MouseClick(object sender, MouseEventArgs e)
		{
			if (isDrawing)
			{
				points[currentIndex] = new Point(e.X, e.Y);
				// 绘制点
				int pointSideLength = 4;
				Rectangle pointRect = new Rectangle(points[currentIndex].X - pointSideLength / 2, points[currentIndex].Y - pointSideLength / 2, pointSideLength, pointSideLength);
				graphics.FillEllipse(polygonBrush, pointRect);
				// 多边形连线
				if (currentIndex > 0 && currentIndex <= 3)
				{
					graphics.DrawLine(linePen, points[currentIndex - 1], points[currentIndex]);
				}
				if (currentIndex == 3)
				{
					graphics.DrawLine(linePen, points[currentIndex], points[0]);
					tip.Text = "点一个点以绘制点";
					tip.ForeColor = Color.Green;
				}
				// 画点
				if (currentIndex == 4)
				{
					graphics.FillEllipse(endPointBrush, pointRect);
					// 结束
					isDrawing = false;
					currentIndex = 0;
					start.Enabled = true;
					tip.ForeColor = Color.Red;
					// 开始判断位置，使用同侧法
					// 先记录点和第一个边的关系
					Point[] side = { points[0], points[1] };
					Point[] startToPoint = { points[0], points[4] };
					bool isFirstSameSide = vectorCrossProduct(side, startToPoint) > 0;
					// 判断后面三条边
					for (int i = 1; i < 4; i++)
					{
						side[0] = points[i];
						if (i == 3)
						{
							side[1] = points[0];
						}
						else
						{
							side[1] = points[i + 1];
						}
						startToPoint[0] = points[i];
						bool isCurrentSameSide = vectorCrossProduct(side, startToPoint) > 0;
						if (isCurrentSameSide != isFirstSameSide)
						{
							tip.Text = "点在多边形外";
							return;
						}
					}
					tip.Text = "点在多边形内";
					return;
				}
				currentIndex++;
			}
		}

		private void start_Click(object sender, System.EventArgs e)
		{
			isDrawing = true;
			start.Enabled = false;
			tip.Text = "在下面区域点击四个点以绘制多边形";
			tip.ForeColor = Color.Purple;
			showArea.Refresh();
		}
	}
}
